import { PickPurpose } from "../strategies/BaseSmartBehavior";
import { Player } from "./player";


export enum PhaseEnum {
    // 开始阶段
    BEGIN,
    // 判定阶段
    JUDGE,
    // 摸牌阶段
    DRAWING,
    // 出牌阶段,
    USING,
    // 弃牌阶段
    THROW,
    // 结束阶段
    END,
    // 不是当前玩家轮次
    OVER

}

export interface PhaseHandler {
    // 判断是否跳过当前阶段
    shouldSkip(player: Player): boolean,
    // 执行当前阶段
    execute(player: Player): Promise<void>,
    // 结束当前阶段
    endPhase(player: Player): void,
    // 下一阶段
    nextPhase(): PhaseEnum,
    // 当前阶段
    currentPhase(): PhaseEnum,
    // 中文
    phaseCN(): string
}

export type PhaseWrapperType<T extends PhaseBaseWrapper> = new (handler: PhaseHandler) => T

export class PhaseBaseWrapper implements PhaseHandler {
    handler: PhaseHandler

    constructor(handler: PhaseHandler) {
        this.handler = handler
    }
    // 判断是否跳过当前阶段
    shouldSkip(player: Player): boolean {
        return this.handler.shouldSkip(player);
    }
    // 执行当前阶段
    async execute(player: Player): Promise<void> {
        return this.handler.execute(player);
    }
    // 结束当前阶段
    endPhase(player: Player): void {
        return this.handler.endPhase(player);
    }
    // 下一阶段
    nextPhase(): PhaseEnum {
        return this.handler.nextPhase();
    }
    // 当前阶段
    currentPhase(): PhaseEnum {
        return this.handler.currentPhase()
    }
    // 中文
    phaseCN(): string {
        return this.handler.phaseCN()
    }
}

class BaseLogPhaseHandler extends PhaseBaseWrapper {

    shouldSkip(player: Player) {
        const msg: string = player.name + "回合" + this.phaseCN() + "start"
        this.addLog(player, msg)
        return super.shouldSkip(player)
    }
    async execute(player: Player) {
        return super.execute(player)
    }
    endPhase(player: Player) {
        const msg: string = player.name + "回合" + this.phaseCN() + "over"
        this.addLog(player, msg)
        // 阶段结束时 根据卡牌代理有效期移除应该失效的卡牌代理  TODO 在手牌区控制器中进行注册
        // const cps = player.getCardProxys()
        // for (const cp of cps) {
        //     if (cp.expirePhase() == this.phaseEnum) {
        //         player.removeCardProxy(cp)
        //     }
        // }

        return super.endPhase(player)
    }
    addLog(player: Player, msg: string): void {
        const gameManager = player.gameManager
        gameManager.appendLog(msg)
    }
}

const DEFAULT_START_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.BEGIN
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {

    },
    phaseCN() {
        return "开始阶段"
    },
    nextPhase() {
        return PhaseEnum.JUDGE
    },
}

const DEFAULT_JUDGE_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.JUDGE
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {
    },
    phaseCN() {
        return "判定阶段"
    },
    nextPhase() {
        return PhaseEnum.DRAWING
    },
}

const DEFAULT_DRAWING_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.DRAWING
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        const cardHeap = player.gameManager.cardHeap
        let card = cardHeap.drawACard()
        if(card) {
            player.handCardAreas.acquireHandCard(card)
        }
        card = cardHeap.drawACard()
        if(card) {
            player.handCardAreas.acquireHandCard(card)
        }
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {

    },
    phaseCN() {
        return "摸牌阶段"
    },
    nextPhase() {
        return PhaseEnum.USING
    },
}

const DEFAULT_USING_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.USING
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        const gm = player.gameManager
        let canPickCards = player.handCardAreas.getHandCards(true).filter(t => t.canuse())
        const [canPickMin, canPickMax] = [1,1]
        const pickPurpose = PickPurpose.USING
        const currentPlayer = player
        const options = {canPickCards, canPickMin, canPickMax, pickPurpose, currentPlayer}
        
        let result = await player.behaviorStragy.waitForPickCard(options)
        while(!result.cancel) {
            gm.clearDeskCard()
            if (result.selectedCards.length == 1) {
                const selectedCard =  result.selectedCards[0]
                const proxyCard = player.handCardAreas.useCard(selectedCard.getSouceCard())
                await proxyCard.use()
            }
            canPickCards = player.handCardAreas.getHandCards(true).filter(t => t.canuse())
            const options = {canPickCards, canPickMin, canPickMax, pickPurpose, currentPlayer}
            result = await player.behaviorStragy.waitForPickCard(options)
        }
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {
        console.log(player)
    },
    phaseCN() {
        return "出牌阶段"
    },
    nextPhase() {
        return PhaseEnum.THROW
    },
}


const DEFAULT_THROWN_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.THROW
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {

    },
    phaseCN() {
        return "弃牌阶段"
    },
    nextPhase() {
        return PhaseEnum.END
    },
}


const DEFAULT_END_PHASE: PhaseHandler = {
    currentPhase(): PhaseEnum {
        return PhaseEnum.END
    },
    shouldSkip(player) {
        return false
    },
    async execute(player) {
        return new Promise<void>(resolve => resolve())
    },
    endPhase(player) {
    },
    phaseCN() {
        return "结束阶段"
    },
    nextPhase() {
        return PhaseEnum.OVER
    },
}

const DEFAULT_PHASE_HANDLER = [ new BaseLogPhaseHandler( DEFAULT_START_PHASE),
    new BaseLogPhaseHandler(DEFAULT_JUDGE_PHASE), new BaseLogPhaseHandler(DEFAULT_DRAWING_PHASE), 
    new BaseLogPhaseHandler(DEFAULT_USING_PHASE), new BaseLogPhaseHandler(DEFAULT_THROWN_PHASE), 
    new BaseLogPhaseHandler(DEFAULT_END_PHASE)
]


class PhaseIterator {

    currentPhaseHandler: PhaseHandler[]

    phaseController: PhaseController

    currentPhase: PhaseEnum

    constructor(phaseController: PhaseController, currentPhaseHandler: PhaseHandler[]) {
        this.phaseController = phaseController
        this.currentPhaseHandler = currentPhaseHandler
        this.currentPhase = PhaseEnum.BEGIN
    }

    getCurrentPhaseHandler(phase: PhaseEnum) {
        return this.currentPhaseHandler[phase]
    }

    registerCurrentPhaseHandler(phase: PhaseEnum, wrapper: PhaseBaseWrapper) {
        this.currentPhaseHandler[phase] = wrapper
    }


    [Symbol.iterator] () {
        let nextPhase = PhaseEnum.BEGIN

        return {
            next: (): IteratorResult<PhaseHandler> => {
                if (nextPhase < this.currentPhaseHandler.length) {
                    const currentPhaseHandler = this.currentPhaseHandler[nextPhase]
                    this.currentPhase = currentPhaseHandler.currentPhase()
                    nextPhase = currentPhaseHandler.nextPhase()
                    return {value: currentPhaseHandler, done: false}
                } else {
                    this.currentPhase = nextPhase
                    return {value: undefined, done: true}
                }
            }
        }

    }

}

class PhaseController {
    
    owner: Player

    defaultPhaseHandler: PhaseHandler[]

    basePhaseHandler: PhaseHandler[]

    phaseIterator: PhaseIterator | undefined

    constructor(owner: Player) {
        this.owner = owner
        this.defaultPhaseHandler = [...DEFAULT_PHASE_HANDLER]
        this.basePhaseHandler = [...DEFAULT_PHASE_HANDLER]
    }

    getBasePhaseHandler(phase: PhaseEnum): PhaseHandler {
        return this.basePhaseHandler[phase]
    }

    registerBasePhaseHandlerByType<T extends PhaseBaseWrapper>(phase: PhaseEnum, target: PhaseWrapperType<T>, forever=false) {
        const basePhase = this.getBasePhaseHandler(phase)
        const wrapper = new target(basePhase)
        this.registerBasePhaseHandler(phase, wrapper, forever)
    }

    registerBasePhaseHandler(phase: PhaseEnum, wrapper: PhaseBaseWrapper, forever=false) {
        this.basePhaseHandler[phase] = wrapper
        if (forever) {
            this.defaultPhaseHandler[phase] = wrapper
        }
    }

    removeBasePhaseHandler() {

    }

    getCurrentPhaseHandler(phase: PhaseEnum): PhaseHandler|undefined {
        if (this.phaseIterator) {
            return this.phaseIterator.getCurrentPhaseHandler(phase)
        } else {
            return undefined
        }
    }

    
    registerCurrentPhaseHandlerByType<T extends PhaseBaseWrapper>(phase: PhaseEnum, target: PhaseWrapperType<T>) {
        const basePhase = this.getBasePhaseHandler(phase)
        const wrapper = new target(basePhase)
        this.registerCurrentPhaseHandler(phase, wrapper)
    }

    registerCurrentPhaseHandler(phase: PhaseEnum, wrapper: PhaseBaseWrapper) {
        if (this.phaseIterator) {
            this.phaseIterator.registerCurrentPhaseHandler(phase, wrapper)
        }
    }

    currentPhase(): PhaseEnum {
        if (this.phaseIterator) {
            return this.phaseIterator.currentPhase
        }
        return PhaseEnum.OVER
    }

    iterator() {
        const currentPhaseHandler = [...this.basePhaseHandler]
        this.phaseIterator = new PhaseIterator(this, currentPhaseHandler)
        return this.phaseIterator
    }

    resetBasePhaseHandler() {
        this.basePhaseHandler = [...this.defaultPhaseHandler]
    }

}

export {
    PhaseController
}
